package com.artifact.mit.mypoint.service.util;

import static com.artifact.mit.mypoint.service.util.Variable.PREFS_NAME;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import android.widget.ImageView;

import com.artifact.mit.mypoint.service.model.SetImage;
import com.artifact.mit.mypoint.service.model.api.BaseApiModel;
import com.artifact.mit.mypoint.service.model.api.Catalogue;
import com.artifact.mit.mypoint.service.model.api.Point;
import com.artifact.mit.mypoint.service.model.api.PointHistory;
import com.artifact.mit.mypoint.service.model.api.PointSource;
import com.artifact.mit.mypoint.service.model.api.User;

/**
 * @deprecated
 * @see com.artifact.mit.mypoint.service.ServiceHandler
 */
public class APICall {

	private static final String BASE_URL = "http://api.pendhapa.com/";
	private static final String LOGIN_API = BASE_URL + "api/account";
	private static final String POINT_API = BASE_URL + "api/point";
	private static final String POINT_SOURCE_API = BASE_URL + "api/pointsource";
	private static final String TRANSACTION_HISTORY = "http://api.pendhapa.com/api/point?date=&last=-1";
	
	// TODO: Lets design a good error handling for all implementation methods
	public static String CATALOGUE_API = BASE_URL + "api/catalogue";
	
	enum HttpMethod {
		POST, GET;
	}
	
	public static <T extends BaseApiModel> T call(Context ctx, String url, Class<T> model, HttpMethod httpMethod){
		SharedPreferences preferences = ctx.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
		HttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(url);
		HttpGet httpGet = new HttpGet(url);
		if (httpMethod == HttpMethod.GET) {
			httpGet.addHeader("Token", getB64(preferences.getString("ctx", "")));
			httpGet.addHeader("Content-Type", "application/json");
		} else {
			httpPost.addHeader("Token", getB64(preferences.getString("ctx", "")));
			httpPost.addHeader("Content-Type", "application/json");	
		}
		try {
			HttpResponse response;
			if (httpMethod == HttpMethod.GET) {
				response = httpClient.execute(httpGet);
			} else {
				response = httpClient.execute(httpPost);
			}
			HttpEntity entity = response.getEntity();
			ObjectMapper mapper = new ObjectMapper();
			String responseString = EntityUtils.toString(entity);
			Log.d("Response call("+model+")", responseString);
			T out = (T) mapper.readValue(responseString, model);
			SharedPreferences.Editor editor = preferences.edit();
			editor.putString("ctx", out.getToken());
			editor.commit();
			return out;
		} catch (NullPointerException e) {
			return null;
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	} 
	
	public static Catalogue catalogue(Context context){
			return call(context, CATALOGUE_API, Catalogue.class, HttpMethod.GET);
	}
	
	public static PointSource pointSource(Context context){
		SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
		HttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(POINT_SOURCE_API);
		httpPost.addHeader("Token", getB64(preferences.getString("ctx", "")));
		httpPost.addHeader("Content-Type", "application/json");
		try {
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			ObjectMapper mapper = new ObjectMapper();
			String responseString = EntityUtils.toString(entity);
			Log.d("Response pointSource()", responseString);
			PointSource points = mapper.readValue(responseString, PointSource.class);
			SharedPreferences.Editor editor = preferences.edit();
			editor.putString("ctx", points.getToken());
			editor.commit();
			return points;
		} catch (NullPointerException e) {
			return null;
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Point point(Context context){
		SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
		HttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(POINT_API);
		httpPost.addHeader("Token", getB64(preferences.getString("ctx", "")));
		httpPost.addHeader("Content-Type", "application/json");
		try {
			Point point = new Point();
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			ObjectMapper mapper = new ObjectMapper();
			String responseString = EntityUtils.toString(entity);
			Log.d("Response point()", responseString);
			point = mapper.readValue(responseString, Point.class);
			SharedPreferences.Editor editor = preferences.edit();
			editor.putString("ctx", point.getToken());
			editor.commit();
			return point;
		} catch (NullPointerException e) {
			return null;
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static PointHistory pointHistory(Context context) {
		SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);				
		HttpClient httpClient = new DefaultHttpClient();				
		HttpGet httpGet = new HttpGet(TRANSACTION_HISTORY);		
		httpGet.addHeader("Token", getB64(preferences.getString("ctx", "")));
		httpGet.addHeader("Content-Type", "application/json");			
		try {						
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			ObjectMapper mapper = new ObjectMapper();
			String responseString = EntityUtils.toString(entity);			
			Log.d("Response Point History", responseString);		
			PointHistory transactionHistory = mapper.readValue(responseString, PointHistory.class);			
			SharedPreferences.Editor editor = preferences.edit();
			editor.putString("ctx", transactionHistory.getToken());			
			editor.commit();	
			return transactionHistory;
		} catch (Exception e) {			
			Log.e("APICall", "Error Point History", e);
		}
		return null;	
	}
	
	public static User authorize(Context context, String username, String password) {
		HttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(LOGIN_API);
		httpPost.addHeader("Authorization", getB64Auth(username, password));
		httpPost.addHeader("Content-Type", "application/json");
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("SerialNo", "12345"));
			httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			User user = new User();
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			ObjectMapper mapper = new ObjectMapper();
			String responseString = EntityUtils.toString(entity);
			Log.d("Response authorize()", responseString);
			user = mapper.readValue(responseString, User.class);
			SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
			SharedPreferences.Editor editor = preferences.edit();
			editor.putString("ctx", user.getToken());
			editor.commit();
			return user;
		} catch (NullPointerException e) {
			return null;
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;	
	}

	public static String getB64Auth(String login, String pass) {
		String source = login + ":" + pass;
		String ret = "Basic " + getB64(source);
		return ret;
	}
	
	public static String getB64(String source){
		return Base64.encodeToString(source.getBytes(), Base64.URL_SAFE | Base64.NO_WRAP);
	}

}
